/*
* @Description: 进度条
* @Author: kanglin
* @Date: 2018/5/9 10:08
* @Copyright: Created by Panxsoft.
*/

<style lang="less" rel="stylesheet/less" type="text/less">
    @import '~src/assets/css/common.less';
    .progressbar{
		padding-top: 50*@rem-per-px;
		padding-bottom: 30*@rem-per-px;
    }
    .progressbar__wrapper{
        height: 10*@rem-per-px;
        background: #f0f0f0;
        border-radius: 5*@rem-per-px;
        position: relative;
    }
    .progressbar__inner{
        overflow: hidden;
        height: 100%;
        position: relative;
    }
    .progressbar__inner__gradient{
        height: 100%;
        border-radius: 8*@rem-per-px;
        position: absolute;
        width: 0;
    }
    .progressbar .percent__tips{
        position: absolute;
        left: 0;
        font-size: 14*@rem-per-px;
        padding:5*@rem-per-px 10*@rem-per-px;
        top: -50*@rem-per-px;
        background: #ffa8b6;
        line-height: 24*@rem-per-px;
        border-radius: 30*@rem-per-px;
        transform: translateX(50%);
        text-align: center;
        color: #ffffff;
		white-space: nowrap;
		text-shadow:  0 0 8px #ccc;
    }

    .progressbar__coordinate__item{
        position: relative;
        margin-top: 16*@rem-per-px;
        text-align: center;
        // margin-right: 15*@rem-per-px;
    }
    .progressbar__coordinate{
        display: flex;
        height: 30*@rem-per-px;
    }
    .progressbar__coordinate__item__value {
        display: inline-block;
        position: absolute;
        right: 0;
        width: 80*@rem-per-px;
        height: 14*@rem-per-px;
        transform: translateX(50%);
        line-height: 14*@rem-per-px;
		font-size: 14*@rem-per-px;
		color: #666666;
    }
    .progressbar__coordinate__item:first-child .progressbar__coordinate__item__value{
        transform: translateX(100%);
        text-align: left;
    }
    .progressbar__coordinate__item:last-child .progressbar__coordinate__item__value{
        transform: translateX(0);
        text-align: right;
    }
    .progressbar__coordinate__item__name {
        position: absolute;
        padding-top: 20*@rem-per-px;
        white-space: nowrap;
    }
</style>

<template>

	<div class="progressbar">
		<div
			ref="progressbar-wrapper"
			:style="wrapper_style"
			class="progressbar__wrapper">
			<div
				:style="tips_style"
				class="percent__tips"
				@touchstart="handleTouchStart">{{ getTips }}</div>
			<div
				:style="inner_style"
				class="progressbar__inner">
				<div
					:style="gradient_bar_style"
					class="progressbar__inner__gradient"/>
			</div>
			<div class="progressbar__coordinate">
				<div
					v-for="(item, index) in coordinate_data"
					:key="index"
					:style="{width: item.width_percent}"

					class="progressbar__coordinate__item">
					<i class="progressbar__coordinate__item__value">
						{{ item.label }}
					</i>
				</div>
			</div>
		</div>
	</div>
</template>

<script>
import gradient from 'gradient-color';

const radio = 1 / 70; // 10rem (设备宽) , 750px (设计稿) -> 设计稿每像素等于 1/75rem 设备宽度
const PROGRESS_ANIMATION = 'all .2s ease-in';

export default {
	name: 'Progressbar',
	props: {
		value: { // 当前值
			type: Number,
			required: true,
		},
		wrapper_color: { // 背景颜色
			type: String,
			default() {
				return '';
			},
		},
		coordinates: { // 坐标配置
			type: Array,
			required: true,
			validator(value) {
				return value.length > 1 && value[0] < value[value.length - 1];
			},
		},
		label: {
			type: String,
			default() {
				return '';
			},
		},
		unit: {
			type: String, // 单位名称
			required: true,
		},
		height: {
			type: Number,
			default() {
				return 10;
			},
		},
		gradientColor: { // 进度条的颜色
			type: Array,
			required: true,
		},
		drag: {
			type: Boolean,
			default() {
				return false;
			},
		},
	},

	data() {
		return {
			wrapper_style: {
				backgroundColor: '#eeeeee',
				height: null,
				borderRadius: null,
			},
			tips_style: {
				transform: null,
				left: null,
				transition: PROGRESS_ANIMATION,
			},
			inner_style: {
				borderRadius: null,
				width: '0',
				transition: PROGRESS_ANIMATION,
			},
			gradient_bar_style: {
				backgroundImage: '#ffff00',
				width: '100%',
			},
			percent: 0,
			coordinate_data: [], // 坐标
			can_drag: false, // 是否能拖拽
			total: 0, // 进度条值
			last_percent: null, // 拖拽前的 percent值
			color_interpolation: [], // 一百个渐变插值
		};
	},

	computed: {
		/**
		 * 计算当前值
		 */
		currentValue() {
			return this.calculateCurrentValue(this.percent, this.coordinates);
		},

		/**
		 *  获取提示信息
		 */
		getTips() {
			const name = this.label;
			const val = Number(this.currentValue).toFixed(1);
			return `${name}: ${val + this.unit}`;
		},

	},

	watch: {
		value() {
			this.initUi();
		},
		percent(value) {
			this.setInnerWidth(value);
			this.setTipsColor(value, this.color_interpolation);
		},
	},

	beforeDestroy() {
		/**
		 *  取消监听
		 */
		document.removeEventListener('touchmove', this.handleTouchMove, false);
		document.removeEventListener('touchend', this.handleTouchEnd, false);
	},

	created() {
		this.initUi();
		if (!this.drag) return;
		this.listentouchEvent();
	},

	methods: {
		/**
         *  初始化组件
         */
		initUi() {
			this.color_interpolation = this.parseGradientColors(this.gradientColor);
			this.percent = this.calculatePercent(this.value, this.coordinates);
			this.coordinate_data = this.resolveCoordinateData(this.coordinates, this.unit);
			this.setWrapperColor(this.wrapper_color);
			this.setGradientStyle(this.gradientColor);
			this.setProgressBarHeight(this.height);
		},

		/**
         * 获取 100 个渐变颜色插值
         */
		parseGradientColors(options) {
			return gradient(options, 100);
		},

		/**
         *  计算总值
         */
		calculateTotal(coordinates) {
			return Math.max(...coordinates) - Math.min(...coordinates);
		},

		/**
         *  设置进度条背景颜色
         *  @param {string} color
         */
		setWrapperColor(color) {
			this.wrapper_style.backgroundColor = color;
		},

		/**
         *  设置进度调进度颜色
         *  @param {string} options
         */
		setGradientStyle(options) {
			let colorString = '90deg';
			options.forEach((item, index, colors) => {
				let str = ` ,${item.color}`;
				if (index === 0) {
					str += ' 0%';
				} else {
					const sum = colors.slice(0, index).reduce((number, color) => number + color.frac, 0);
					str += ` ${Math.round(sum * 100)}%`;
				}
				colorString += str;
			});
			// console.log(colorString);
			this.gradient_bar_style.backgroundImage = `linear-gradient(${colorString})`;
			this.$nextTick(() => {
				const { width } = this.$refs['progressbar-wrapper'].getBoundingClientRect();
				this.gradient_bar_style.width = `${width}px`;
			});
		},

		/**
         *  计算进度百分比
         *  @param {number} value
         *  @param {[number]} data
         *  @return {number} percent -带百分号
         */
		calculatePercent(value, coordinates) {
			let percent = 0;
			const start = Math.min(...coordinates);
			const end = Math.max(...coordinates);
			const total = end - start;
			if (total > 0) {
				const ratio = (value - start) / total;
				percent = ratio * 100;
			}
			return percent;
		},

		/**
		 *  计算当前值
		 */
		calculateCurrentValue(percent, coordinates) {
			const start = Math.min(...coordinates);
			const end = Math.max(...coordinates);
			const total = end - start;
			return start + parseFloat((percent / 100) * total);
		},

		/**
		 *  设置进度条宽tips偏移
		 *  @param {number} percent
		 */
		setInnerWidth(percent) {
			let p = Math.min(100, percent);
			p = Math.max(0, p);
			this.inner_style.width = `${p}%`;
			this.tips_style.transform = `translateX(${p * -1}%)`;
			this.tips_style.left = `${p}%`;
		},

		/**
         *  解析坐标占总长度百分数
         * @param {array} coordinates
         * @param {string} unit 单位名
         * @param {array} intervals 单位名
         */
		resolveCoordinateData(coordinates, unit) {
			const data = [];
			coordinates.forEach((item, index) => {
				if (index === 0) {
					data.push({
						width_percent: '0',
						label: '0',
						interval_name: '',
					});
				} else {
					const interval = coordinates[index] - coordinates[index - 1];
					const interval_percent = interval / (Math.max(...coordinates) - Math.min(...coordinates));
					data.push({
						width_percent: `${interval_percent * 100}%`,
						label: item + unit,
					});
				}
			});
			return data;
		},

		/**
         *  设置进度调调高度
         */
		setProgressBarHeight(h) {
			if (typeof h === 'number') {
				this.wrapper_style.height = `${h * radio}rem`;
				this.wrapper_style.borderRadius = `${(h / 2) * radio}rem`;
				this.inner_style.borderRadius = `${(h / 2) * radio}rem`;
			}
		},

		/**
         * 处理 touch start 事件
         */
		handleTouchStart() {
			if (!this.drag) return;
			this.can_drag = true;
			this.last_percent = this.percent;
			this.inner_style.transition = null;
			this.tips_style.transition = null;
		},

		/**
         *  监听并处处理 touchend 事件
         */
		listentouchEvent() {
			document.addEventListener('touchend', this.handleTouchEnd);
			document.addEventListener('touchmove', this.handleTouchMove);
		},

		/**
         *  处理 touch end 事件
         */
		handleTouchEnd() {
			if (this.can_drag) {
				this.can_drag = false;
				this.inner_style.transition = PROGRESS_ANIMATION;
				this.tips_style.transition = PROGRESS_ANIMATION;
				this.percent = this.last_percent;
			}
		},

		/**
         *  处理移动
         */
		handleTouchMove(event) {
			if (!this.can_drag) return;
			const { clientX } = event.changedTouches[0];
			const { left, width } = this.$refs['progressbar-wrapper'].getBoundingClientRect();
			let currentLength = clientX - left;
			currentLength = Math.max(currentLength, 0);
			currentLength = Math.min(currentLength, width);
			const percent = (currentLength / width) * 100;
			this.percent = percent;
		},

		/**
         * 设置提示颜色
         * @param current_percent
         */
		setTipsColor(current_percent, colors) {
			let index = Math.ceil(current_percent);
			index = (index - 1) >= 0 ? index - 1 : 0;
			index = Math.min(colors.length - 1, index); // 处理超出边界情况
			index = Math.max(0, index); // 处理超出边界情况
			this.tips_style.backgroundColor = colors[index];
		},

	},
};
</script>
